package com.twu.biblioteca;


import com.twu.biblioteca.actions.BibliotechaCommandFactoryImpl;
import com.twu.biblioteca.actions.BibliotechaCommandsFactory;
import com.twu.biblioteca.controller.LibraryControllerImpl;
import com.twu.biblioteca.controller.LoginControllerImpl;
import com.twu.biblioteca.domain.Book;
import com.twu.biblioteca.domain.LibraryUser;
import com.twu.biblioteca.domain.Movie;
import com.twu.biblioteca.repository.LibraryEntityRepository;
import com.twu.biblioteca.repository.Repository;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;

public class BibliotecaApp {


    private static LoginControllerImpl loginController;

    public static void setActionPerformer(ActionPerformer actionPerformer) {
        BibliotecaApp.actionPerformer = actionPerformer;
    }

    private static ActionPerformer actionPerformer;

    public static void initialiseDependencies() {
        Repository<Book> bookRepository = new LibraryEntityRepository<Book>(new ArrayList<Book>() {{
            add(new Book("H.Lee1960", "To Kill a Mockingbird", "Harper Lee", 1960));
            add(new Book("J.Steinbeck1937", "Of Mice and Men", "John Steinbeck", 1937));
            add(new Book("J.Austen1913", "Pride and Prejudice", "Jane Austen", 1913));
        }});
        Repository<Book> loanRepository = new LibraryEntityRepository<Book>(new ArrayList<Book>());

        Repository<Movie> movieRepository = new LibraryEntityRepository<Movie>(new ArrayList<Movie>()){{
            add(new Movie("D.Lynch2001", "Mulholland Drive" , "David Lynch", 2001, 9));
            add(new Movie("W.Andersion2014", "Grand Budapest Hotel", "Wes Anderson", 2014, 6));
        }};

        final LibraryUser initialUser = new LibraryUser.Builder("123-4567", "Pa55word")
                .emailAddress("paul.nunnerley@thoughtworks.com")
                .phoneNumber("07578710691")
                .setFirstName("Paul")
                .setLastName("Nunnerley")
                .build();

        loginController = new LoginControllerImpl(new LibraryEntityRepository<LibraryUser>(new ArrayList<LibraryUser>() {{
            add(initialUser);
        }}));


        Repository<Movie> loanedMoviesRepository = new LibraryEntityRepository<Movie>(new ArrayList<Movie>());


        LibraryControllerImpl<Book> bookController = new LibraryControllerImpl<Book>(bookRepository, loanRepository, loginController);
        LibraryControllerImpl<Movie> movieController = new LibraryControllerImpl<Movie>(movieRepository, loanedMoviesRepository, loginController);

        BibliotechaCommandsFactory bibliotechaCommandFactory = new BibliotechaCommandFactoryImpl(bookController, movieController, loginController);
        actionPerformer = new ActionPerformer(bibliotechaCommandFactory);
    }

    public static void main(String[] args) {
        initialiseDependencies();

        System.out.println("Before using this system you must login");
        System.out.println("Please enter your Library Id: ");
        String userId = readInputFromUser();

        System.out.println("Please enter your password");
        String password = readInputFromUser();

        if(!loginController.login(userId, password)){
            System.out.println("The username and password you entered is an invalid combination");
            System.exit(1);
        }

        printWelcomeMessage();
        performActionsUntilUserExists();
    }

    private static void performActionsUntilUserExists() {
        boolean shouldExit;
        do {
            String input = readInputFromUser();
            shouldExit = performAction(input);
        } while (!shouldExit);
    }

    private static void printWelcomeMessage() {
        System.out.println("Welcome to the Bibliotecha!");
        System.out.println("Menu Options: list, listMovies, withdrawBook <id>, withdrawMovie <id>, returnMovie <id>, returnBook <id>, quit");
        System.out.println("Extra Options: listWithdrawn, showDetails");
    }

    private static String readInputFromUser() {
        BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in));

        String input = null;
        try {
            System.out.print("> ");
            input = stdIn.readLine();
        } catch (IOException exception) {
            System.err.println("Could not read standard input");
            System.exit(-1);
        }
        return input;
    }

    public static boolean performAction(String actionName) {
        if (actionName.equalsIgnoreCase("Quit")) {
            return true;
        }
        boolean actionPerformedSuccessfully = performActionIfAvailable(actionName);
        if (actionPerformedSuccessfully) return false;

        System.out.println("Invalid Option");
        return false;
    }

    private static boolean performActionIfAvailable(String actionName) {
        String[] tokens = actionName.split(" ");

        String action = tokens[0];
        String parameter = (tokens.length > 1) ?  tokens[1] : null;

        return actionPerformer.execute(action, parameter);
    }



}
